//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
// PHOTOGENIC SAN ANDREAS effect.txt file
//
// CREDITS:
// Boris Vorontsov: ENBSeries
// Marty McFly: Autor of the Letterbox code
// ZIMMER: Port and Modification of Shaders, Shaders setup and author of this file.
// 
// Please do not distribute this file without credits.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++

//LETTERBOX
#define Letterbox

//LUMA SHARPENING
float NoiseAmount=0.00;
float offset_bias=1.0;
float sharp_strength_luma=0.11;
float sharp_clamp=0.03;

//LENS DISTORTION
float ChromaticAmount=0.0; 
float LensSize=0.534;   
float LensDistortion=0.2;   

//VIGNETTE
float VignetteAmount=0.0;
float VignetteCurve=1.5;
float VignetteRadius=1.85;
float3 VignetteColor = float3(0.25, 0.25, 0.0);

//keyboard controlled temporary variables (in some versions exists in the config file). Press and hold key 1,2,3...8 together with PageUp or PageDown to modify. By default all set to 1.0
float4	tempF1; //0,1,2,3
float4	tempF2; //5,6,7,8
float4	tempF3; //9,0
//x=generic timer in range 0..1, period of 16777216 ms (4.6 hours), w=frame time elapsed (in seconds)
float4	Timer;
//x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
float4	ScreenSize;
float ScreenScaleY;
float4 SunDirection;
//textures
texture2D texColor;
texture2D texNoise;

sampler2D SamplerColor = sampler_state
{
	Texture   = <texColor>;
	MinFilter = LINEAR;
	MagFilter = LINEAR;
	MipFilter = NONE;//NONE;
	AddressU  = Clamp;
	AddressV  = Clamp;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

sampler2D SamplerNoise = sampler_state
{
	Texture   = <texNoise>;
	MinFilter = POINT;
	MagFilter = POINT;
	MipFilter = NONE;//NONE;
	AddressU  = Wrap;
	AddressV  = Wrap;
	SRGBTexture=FALSE;
	MaxMipLevel=0;
	MipMapLodBias=0;
};

struct VS_OUTPUT_POST {
	float4 vpos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

struct VS_INPUT_POST {
	float3 pos  : POSITION;
	float2 txcoord : TEXCOORD0;
};

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
{
	VS_OUTPUT_POST OUT;

	float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	OUT.vpos=pos;
	OUT.txcoord.xy=IN.txcoord.xy;

	return OUT;
}

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//--------------------Fast Approximate Anti-Aliasing --------------------------
//         FXAA v2 CONSOLE by TIMOTHY LOTTES @ NVIDIA   
//          Ported to ENBSeries by MysTer92 (Svyatoslav Gampel)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++



float4 PS_PostProcess(VS_OUTPUT_POST i) : COLOR
{
	#define FXAA_SUBPIX_SHIFT (1.0/8.0)
	#define FXAA_REDUCE_MIN   (1.0/32.0)
	#define FXAA_REDUCE_MUL   (1.0/16.0)
	#define FXAA_SPAN_MAX     8.0

	half2 rcpFrame = half2(1/ScreenSize.x, 1/(ScreenSize.x/ScreenSize.z));

	half4 posPos;
	posPos.xy = i.txcoord.xy;
	posPos.zw = posPos.xy - (rcpFrame.xy * (0.5 + FXAA_SUBPIX_SHIFT));

	half3 rgbNW = tex2D(SamplerColor, posPos.zw ).xyz;
	half3 rgbNE = tex2D(SamplerColor, posPos.zw + half2(rcpFrame.x, 0.0) ).xyz;
	half3 rgbSW = tex2D(SamplerColor, posPos.zw + half2(0.0, rcpFrame.y) ).xyz;
	half3 rgbSE = tex2D(SamplerColor, posPos.zw +rcpFrame.xy ).xyz;
	half3 rgbM  = tex2D(SamplerColor, posPos.xy).xyz;
       
	half3 luma = half3(0.2126, 0.7152, 0.0722);
	half lumaNW = dot(rgbNW, luma);
	half lumaNE = dot(rgbNE, luma);
	half lumaSW = dot(rgbSW, luma);
	half lumaSE = dot(rgbSE, luma);
	half lumaM  = dot(rgbM,  luma);
       
	half lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
	half lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
       
	half2 dir; 
       
	half lumaNWNE = lumaNW + lumaNE;
	half lumaSWSE = lumaSW + lumaSE;
       
	dir.x = -((lumaNWNE) - (lumaSWSE));
	dir.y =  ((lumaNW + lumaSW) - (lumaNE + lumaSE));
       
	half dirReduce = max( (lumaSWSE + lumaNWNE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
	half rcpDirMin = 1.0/(min(abs(dir.x), abs(dir.y)) + dirReduce);
	dir = min(half2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX), max(half2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * rcpFrame.xy;
             
	half3 rgbA = (1.0/2.0) * (tex2D(SamplerColor, posPos.xy + dir * (1.0/3.0 - 0.5) ).xyz + tex2D(SamplerColor, posPos.xy + dir * (2.0/3.0 - 0.5) ).xyz);
	half3 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (tex2D(SamplerColor, posPos.xy + dir * (0.0/3.0 - 0.5) ).xyz + tex2D(SamplerColor, posPos.xy + dir * (3.0/3.0 - 0.5) ).xyz);
	half lumaB = dot(rgbB, luma);
     
	if((lumaB < lumaMin) || (lumaB > lumaMax))
 		return half4(rgbA, 1.0);
       
	return float4(rgbB, 1.0);
}

float4 PS_PostProcess_Sharp_Noise(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4 res = 0;
	float4 tex=0.0;
	tex.xy=IN.txcoord.xy;

	float3 ori = tex2D(SamplerColor, tex).rgb;       // ori = original pixel

	float2 p;
	p.x = 1.0/ScreenSize.x;
	p.y=p.x/ScreenSize.z;

	// -- Gaussian filter --
	//   [ .50, .50, .50]     [ 1 , 1 , 1 ]
	//   [ .50,    , .50]  =  [ 1 ,   , 1 ]
 	//   [ .50, .50, .50]     [ 1 , 1 , 1 ]

    float3 blur_ori = tex2D(SamplerColor, tex + float2(0.5 * p.x,-p.y * offset_bias)).rgb;  // South South East
    blur_ori += tex2D(SamplerColor, tex + float2(offset_bias * -p.x,0.5 * -p.y)).rgb; // West South West
    blur_ori += tex2D(SamplerColor, tex + float2(offset_bias * p.x,0.5 * p.y)).rgb; // East North East
    blur_ori += tex2D(SamplerColor, tex + float2(0.5 * -p.x,p.y * offset_bias)).rgb; // North North West

    //blur_ori += (2 * ori); // Probably not needed. Only serves to lessen the effect.
	
    blur_ori /= 4.0;  //Divide by the number of texture fetches

    //sharp_strength_luma *= 0.666; // Adjust strength to aproximate the strength of pattern 2
	
	// -- Calculate the sharpening --  
	float3 sharp = ori - blur_ori;  //Subtracting the blurred image from the original image
  
	// -- Adjust strength of the sharpening --
	float sharp_luma = dot(sharp, sharp_strength_luma); //Calculate the luma and adjust the strength

	// -- Clamping the maximum amount of sharpening to prevent halo artifacts --
	sharp_luma = clamp(sharp_luma, -sharp_clamp, sharp_clamp);  //TODO Try a curve function instead of a clamp

	// -- Combining the values to get the final sharpened pixel	--
  //float4 done = ori + sharp_luma;    // Add the sharpening to the original.
	float4 done = tex2D(SamplerColor, tex) + sharp_luma;    // Add the sharpening to the input color.

 

	// -- Grain noise
	float origgray=dot(done.xyz, 0.333);
	//origgray=max(origgray, res.z);
	tex.xy=IN.txcoord.xy*16.0 + origgray;
	float4 cnoi=tex2Dlod(SamplerNoise, tex);
	done=lerp(done, (cnoi.x+0.5)*done, NoiseAmount*saturate(1.0-origgray*1.8));


	done.w=1.0;
	return done;
}

float4 PS_PostProcess2(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
float4 res;
float4 coord=0.0;

coord.xy=IN.txcoord.xy;
float4 origcolor;

coord.w=0.0;


origcolor=tex2Dlod(SamplerColor, coord);

// coord.x=IN.txcoord.x-(1.5/ScreenSize);
// float4 lshift=tex2Dlod(SamplerColor, coord);
// coord.x=IN.txcoord.x+(1.5/ScreenSize);
// float4 rshift=tex2Dlod(SamplerColor, coord);


float2 offset[8]=
{
 float2(1.0, 1.0),
 float2(-1.0, -1.0),
 float2(-1.0, 1.0),
 float2(1.0, -1.0),

 float2(1.41, 0.0),
 float2(-1.41, 0.0),
 float2(0.0, 1.41),
 float2(0.0, -1.41)
};
int i=0;

float4 tcol=origcolor;
float2 invscreensize=1.0/ScreenSize;
invscreensize.y=invscreensize.y/ScreenScaleY;
//for (i=0; i<8; i++) //higher quality
/*	for (i=0; i<4; i++)
{
 float2 tdir=offset[i].xy;
 coord.xy=IN.txcoord.xy+tdir.xy*invscreensize*SamplingRange;//*1.0;
 float4 ct=tex2Dlod(SamplerColor, coord);

 tcol+=ct;
}
tcol*=0.2; // 1.0/(4+1)
//tcol*=0.111; // 1.0/(8+1)  //higher quality
*/

float3 eta = float3(1.0+ChromaticAmount*0.9,1.0+ChromaticAmount*0.6,1.0+ChromaticAmount*0.3);
float2 center;
center.x = coord.x-0.5;
center.y = coord.y-0.5;
float LensZoom = 1.0/LensSize;

float r2 = (IN.txcoord.x-0.5) * (IN.txcoord.x-0.5) + (IN.txcoord.y-0.5) * (IN.txcoord.y-0.5);     
float f = 0;

if( 0.0 == 0.0){
	f = 1 + r2 * LensDistortion;
}else{
                f = 1 + r2 * (LensDistortion + 0.0 * sqrt(r2));
};

float x = f*LensZoom*(coord.x-0.5)+0.5;
float y = f*LensZoom*(coord.y-0.5)+0.5;
float2 rCoords = (f*eta.r)*LensZoom*(center.xy*0.5)+0.5;
float2 gCoords = (f*eta.g)*LensZoom*(center.xy*0.5)+0.5;
float2 bCoords = (f*eta.b)*LensZoom*(center.xy*0.5)+0.5;

float4 inputDistord = float4(tex2D(SamplerColor,rCoords).r , tex2D(SamplerColor,gCoords).g ,tex2D(SamplerColor,bCoords).b, tex2D(SamplerColor,float2(x,y)).a);
return float4(inputDistord.r,inputDistord.g,inputDistord.b,1);

res.w=1.0;
return res;
}

float4 PS_Vignette(VS_OUTPUT_POST IN, float2 vPos : VPOS) : COLOR
{
	float4	res;
	float3	origcolor=tex2D(SamplerColor, IN.txcoord.xy);

	float2	uv=(IN.txcoord.xy-0.5)*VignetteRadius;
	float	vignette=saturate(dot(uv.xy, uv.xy));
	vignette=pow(vignette, VignetteCurve);
	res.xyz=lerp(origcolor.xyz, VignetteColor, vignette*VignetteAmount);

	res.w=1.0;
	return res;
}

float4 PS_Final(VS_OUTPUT_POST f,float2 z:VPOS):COLOR
{
        float2 t=f.txcoord.xy;float3 r=tex2D(SamplerColor,t).xyz;
        #ifdef Letterbox
        r.xyz=t.y>.1&&t.y<.9?r.xyz:0.;
        #endif
        return float4(r,1);
}

technique PostProcess //FXAA
{
pass P0
        {

                VertexShader = compile vs_3_0 VS_PostProcess();
                PixelShader  = compile ps_3_0 PS_PostProcess_Sharp_Noise();

        }
}

technique PostProcess2 //FXAA
{
pass P0
        {

                VertexShader = compile vs_3_0 VS_PostProcess();
                PixelShader  = compile ps_3_0 PS_PostProcess();

        }
}

technique PostProcess3
{
pass P0
        {

                VertexShader = compile vs_3_0 VS_PostProcess();
                PixelShader  = compile ps_3_0 PS_PostProcess_Sharp_Noise();

        }
}

technique PostProcess4
{
pass P0
        {

                VertexShader = compile vs_3_0 VS_PostProcess();
                PixelShader  = compile ps_3_0 PS_PostProcess2();

        }
}

technique PostProcess5
{
pass P0
        {

                VertexShader = compile vs_3_0 VS_PostProcess();
                PixelShader  = compile ps_3_0 PS_Vignette();

        }
}

technique PostProcess6 
{
pass P0
        {

                VertexShader = compile vs_3_0 VS_PostProcess();
                PixelShader  = compile ps_3_0 PS_Final();

        }
}

